package com.dronff.handler;

import com.dronff.Result;
import com.dronff.interceptor.TangProtocolRPCProxyObjectInterceptor;
import com.dronff.protocol.TangProtocol;
import com.dronff.stat.ProtocolType;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.apache.log4j.Logger;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class TangProtocolInvokerInboundHandler extends SimpleChannelInboundHandler<TangProtocol> {
    static final Logger logger = Logger.getLogger(TangProtocolInvokerInboundHandler.class);
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TangProtocol tangProtocol) throws Exception {
        if (ProtocolType.INVOKE == tangProtocol.getType()) {
            // 处理请求数据
            Class<?> clazz = Class.forName(tangProtocol.getClazzName());
            Class[] paramTypes = new Class[tangProtocol.getMethodTypes().length];
            final int[] i = {0};
            Arrays.stream(tangProtocol.getMethodTypes()).forEach(
                    new Consumer<String>() {
                        @Override
                        public void accept(String s) {
                            try {
                                paramTypes[i[0]++] = Class.forName(s);
                            } catch (ClassNotFoundException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
            );
            Method method = clazz.getDeclaredMethod(tangProtocol.getMethodName(),paramTypes);
            Object o = clazz.newInstance();
            Object invoke = method.invoke(o, tangProtocol.getParams());
            // 将协议设置为响应类型
            tangProtocol.setType(ProtocolType.RESPONSE);
            // 设置调用结果
            tangProtocol.setResponseResult(invoke);
            // 写回数据
            channelHandlerContext.channel().writeAndFlush(tangProtocol);
        }else{
            // 处理响应数据
            logger.debug("收到了一个响应数据");
            logger.debug("内容" + tangProtocol.getResponseResult());
            // 唤醒线程
            Result result = TangProtocolRPCProxyObjectInterceptor.resultMap.get(tangProtocol.getReqId());
            synchronized (result.getLock()){
                result.getLock().notifyAll();
            }
        }

    }

    private Method parseMethod(Class<?> clazz,String methodName) throws ClassNotFoundException, NoSuchMethodException {
        String[] multiPartMethod = methodName.split(":");
        List<Class<?>> paramClazz = new ArrayList<>();
        // 解析参数列表
        String[] paramClazzNames = multiPartMethod[1].split(",");
        for (int i = 0; i < paramClazzNames.length; i++) {
            paramClazz.add(
                    Class.forName(paramClazzNames[i])
            );
        }
        Class[] clazzArr = (Class[]) paramClazz.toArray();
        Method declaredMethod = clazz.getDeclaredMethod(
                multiPartMethod[0],
                clazzArr
        );
        return declaredMethod;
    }
}
